import React, { Component, Fragment } from 'react';
import { connect } from 'react-redux';
import {
    Breadcrumb,
    Button,
    Container,
    Col,
    Form,
    Row,
    Spinner
} from 'react-bootstrap';
import queryString from 'query-string';
import classNames from 'classnames';
import Highlight from 'react-highlight'
import $ from 'jquery';
import 'highlight.js/styles/monokai-sublime.css'

import { 
    URL,
    TASKDETAIL_FROM,
    TaskStatus,
    CODE
} from '../../config';

import {
    function_get_task,
    function_set_tester,
    function_set_admin
} from '../../actions/task';
import {
    function_test_task,
    function_test_success,
    function_pre_test_success,
    function_test_abort,
    function_pre_test_abort,
    function_pre_test_task,
    function_deploying_task,
    function_set_task_failured,
    function_diff_branch,
} from '../../actions/deploy';
import {
    function_get_project
} from '../../actions/project';
import DeployContainer from './deploy';

import './less/detail.css'; 

class App extends Component {

    state = {
        pid: parseInt(queryString.parse(this.props.location.search).pid),
        tid: parseInt(queryString.parse(this.props.location.search).tid),
        from: parseInt(queryString.parse(this.props.location.search).from),
        testHost: null, //测试环境部署的服务器
        prevHost: null, //预发布环境部署的服务器
        projectName: "", //项目名称
        taskName: "", //任务名称
        deployStatus: "", //上线状态
        diffFileList: {}, //文件对比
    }

    componentDidMount(){
        this.getProject();
        this.getTask();
    }

    componentDidUpdate(prevProps){
        if(this.state.projectName === "" && Object.keys(this.props.projectList).length > 0){
            let data = [];
            for (let item of this.props.projectList[this.state.pid].developer) {
                let uid = item.uid;
                data.push({ id: uid, text: uid });
            }
            data = [];
            for (let item of this.props.projectList[this.state.pid].tester) {
                let uid = item.uid;
                data.push({ id: uid, text: uid });
            }
            $(this.refs.tester).select2({
                placeholder: "选择测试人员",
                data,
            });
            data = [];
            for (let item of this.props.projectList[this.state.pid].admin) {
                let uid = item.uid;
                data.push({ id: uid, text: uid });
            }
            $(this.refs.admin).select2({
                placeholder: "选择上线人员",
                data,
            });
            this.setState({
                projectName: this.props.projectList[this.state.pid].name
            });
        }
        
    }

    getTask(){
        function_get_task(this.state.pid, this.state.tid, this.props.dispatch, (data)=>{
            if(data.status === TaskStatus.TESTING){
                this.setState({
                    testHost: data.testHost
                });
            }
            if(data.status === TaskStatus.PRE_TESTING){
                this.setState({
                    prevHost: data.prevHost
                });
            }
            $(this.refs.admin).val(this.props.admin.uid).trigger('change');
            $(this.refs.tester).val(this.props.tester.uid).trigger('change');
        });
    }

    handleChgTester(){
        let new_tester = parseInt($(this.refs.tester).val());
        if(new_tester !== this.props.tester.uid){
            function_set_tester(this.state.pid, this.state.tid, new_tester, (result)=>{
                if (result.code === CODE.SUCCESS) {
                    this.getTask();
                    alert("修改测试人员成功");
                }else{
                    $(this.refs.tester).val(this.props.tester.uid).trigger('change');
                    alert(result.message);
                }
            });
        }
    }

    handleChgReviewer(){
        let new_reviewer = parseInt($(this.refs.admin).val());
        if(new_reviewer !== this.props.admin.uid){
            function_set_admin(this.state.pid, this.state.tid, new_reviewer, (result)=>{
                if (result.code === CODE.SUCCESS) {
                    this.getTask();
                    alert("修改上线人员成功");
                }else{
                    $(this.refs.admin).val(this.props.admin.uid).trigger('change');
                    alert(result.message);
                }
            });
        }
    }

    handleTesting(reloadFlg){
        if(this.props.deployStatus === TaskStatus.WAIT_FOR_TEST && this.props.taskServs[0].servsObject.testHost.length === 0){
            function_test_task(this.state.pid, this.state.tid, "", this.props.dispatch, ()=>{});
        }else{
            let testHost = $(this.refs.testHost).val();
            function_test_task(this.state.pid, this.state.tid, testHost, this.props.dispatch, ()=>{
                this.setState({testHost});
                this.DeployContaine.deploy(reloadFlg, ()=>{
                });
            });
        }
    }

    handlePreTesting(reloadFlg){
        let prevHost = $(this.refs.prevHost).val();
        function_pre_test_task(this.state.pid, this.state.tid, prevHost, this.props.dispatch, ()=>{
            this.setState({prevHost});
            this.DeployContaine.deploy(reloadFlg, ()=>{
            });
        });
    }

    handleDeployFailured(){
        function_set_task_failured(this.state.pid, this.state.tid, this.props.dispatch, ()=>{});
    }

    handleDeploy(reloadFlg){
        function_deploying_task(this.state.pid, this.state.tid, this.props.dispatch, ()=>{
            this.DeployContaine.deploy(reloadFlg, ()=>{
            });
        });
    }

    abortTest(){
        function_test_abort(this.state.pid, this.state.tid, this.props.dispatch, ()=>{});
    }

    abortPreTest(){
        function_pre_test_abort(this.state.pid, this.state.tid, this.props.dispatch, ()=>{});
    }

    handlePreTestSuccess(){
        function_pre_test_success(this.state.pid, this.state.tid, this.props.dispatch, ()=>{});
    }

    handleTestSuccess(){
        function_test_success(this.state.pid, this.state.tid, this.props.dispatch, ()=>{});
    }

    onDeployContainerRef = (ref) => {
        this.DeployContaine = ref;
    }

    getProject(){
        function_get_project(this.state.pid, this.props.dispatch, (adminArr, testerArr, developerArr) => {
            let data = [];
            for (let item of adminArr) {
              data.push({ id: item.uid, text: item.nickname });
            }
            $(this.refs.admin).empty().select2({
              placeholder: "选择上线人员",
              data,
            });
            data = [];
            for (let item of testerArr) {
                data.push({ id: item.uid, text: item.nickname });
            }
            $(this.refs.tester).empty().select2({
              placeholder: "选择测试人员",
              data,
            });
            $(this.refs.admin).val(this.props.admin.uid).trigger('change');
            $(this.refs.tester).val(this.props.tester.uid).trigger('change');
        });
    }

    diffBranch(servsId){
        let diffFileList = this.state.diffFileList;
        diffFileList[servsId] = {};
        diffFileList[servsId].list = [];
        diffFileList[servsId].selected = 0;
        diffFileList[servsId].loading = true;
        this.setState({diffFileList});
        function_diff_branch(this.props.deployUrl, this.state.pid, this.state.tid, servsId, (list)=>{
            diffFileList[servsId].list = list;
            diffFileList[servsId].loading = false;
            this.setState({diffFileList});
        });
    }

    handleSetDiffFile(servsId, fileIndex){
        let diffFileList = this.state.diffFileList;
        if(diffFileList[servsId].selected === fileIndex){
            diffFileList[servsId].selected = -1;
        }else{
            diffFileList[servsId].selected = fileIndex;
        }
        this.setState({diffFileList});
    }

    render () {
        return (
            <Container>
            {this.state.from === TASKDETAIL_FROM.DEPLOYING ?
                <Breadcrumb>
                    <Breadcrumb.Item href={URL.main_page}>主页</Breadcrumb.Item>
                    <Breadcrumb.Item href={URL.deploying_page}>待上线请求</Breadcrumb.Item>
                    <Breadcrumb.Item active>明细</Breadcrumb.Item>
                </Breadcrumb>
            : null}
            {this.state.from === TASKDETAIL_FROM.ADDTASK ?
                <Breadcrumb>
                    <Breadcrumb.Item href={URL.main_page}>主页</Breadcrumb.Item>
                    <Breadcrumb.Item href={URL.addtask_page+"?pid="+this.state.pid}>提交上线单</Breadcrumb.Item>
                    <Breadcrumb.Item active>详情</Breadcrumb.Item>
                </Breadcrumb>
            : null}
                <div>
                    <Row>
                        <Col sm={8}>
                            <div className={classNames("setting-box","task-detail")}>
                                <Row>
                                    <Col className="field">上线单标题</Col>
                                    <Col className="content">{this.props.taskName}</Col>
                                </Row>
                                <Row>
                                    <Col className="field">所属项目</Col>
                                    <Col className="content">{this.state.projectName}</Col>
                                </Row>
                                <Row>
                                    <Col className="field">备注信息</Col>
                                    <Col className="content">{this.props.markContent}</Col>
                                </Row>

                                {this.props.taskServs.map(item => <div key={item.servsId}>
                                    <Row>
                                        <Col className="field">{"微服务" + item.servsObject.serviceName}</Col>
                                        <Col className="content">{"从 分支"+item.branch+" 合并到  分支"+item.servsObject.targetBranch}</Col>
                                    </Row>
                                    {!(item.sqls.length === 1 && item.sqls[0] === "") ?
                                        <Row>
                                            <Col className="field">sql脚本</Col>
                                            <Col className="content">
                                                <Highlight language="sql" innerHTML={true}>
                                                    {"<pre><code class=\"hljs\">" + item.sqls.join(";\n").replace(/\n/g,"<br />") + ";</code></pre>"}
                                                </Highlight>
                                            </Col>
                                        </Row>
                                    : null}
                                    {!(item.jobs.length === 1 && item.jobs[0] === "") ?
                                        <Row>
                                            <Col className="field">job脚本</Col>
                                            <Col className="content">
                                                <Highlight language="bash" innerHTML={true}>
                                                    {"<pre><code class=\"hljs\">" + item.jobs.join(";\n").replace(/\n/g,"<br />") + ";</code></pre>"}
                                                </Highlight>
                                            </Col>
                                        </Row>
                                    : null}
                                    <Row className="diffFiles">
                                        {((item.servsId in this.state.diffFileList) && (this.state.diffFileList[item.servsId].list.length>0)) ?
                                            <Fragment>
                                                <h5>修改文件列表</h5>
                                                {this.state.diffFileList[item.servsId].list.map((item2, index2) => 
                                                    <Col key={index2} className="content">
                                                        <div className="title" onClick={this.handleSetDiffFile.bind(this, item.servsId, index2)}>
                                                            {item2.changeType === "DELETE" ? "删除" : (item2.changeType === "ADD" ? "新增" : "修改")} {item2.fileName}
                                                        </div>
                                                        {index2 === this.state.diffFileList[item.servsId].selected ?
                                                            <div className="contentBox">
                                                                {item2.diffContentLine.map((item3, index3) => 
                                                                    <p key={index3} className={
                                                                        item3.operate === "+" ? "plus" : (item3.operate === "-" ? "minus" : "normal")
                                                                    }>
                                                                        <i>{item3.operate !== "+"?item3.oldLineNum:" "}</i>
                                                                        <i>{item3.operate !== "-"?item3.newLineNum:" "}</i>
                                                                        <i className="sub-type">{item3.operate}</i>
                                                                        {item3.content}
                                                                    </p>
                                                                )}
                                                            </div>
                                                        : null}
                                                    </Col>
                                                )}
                                            </Fragment>
                                        :
                                        (item.servsId in this.state.diffFileList) && (this.state.diffFileList[item.servsId].loading) ? <Spinner animation="grow" />: <Button variant="link" onClick={this.diffBranch.bind(this, item.servsId)}>点击查看文件修改</Button>}
                                    </Row>
                                </div>)}
                            </div>
                        </Col>
                        <Col sm={4}>
                            <Form>
                                <Form.Group as={Row}>
                                    <Form.Label column sm="3">
                                        测试人员
                                    </Form.Label>
                                    <Col sm="5">
                                        <Form.Control ref="tester" as="select" disabled={this.props.developer.uid !== this.props.myuid}/>
                                    </Col>
                                    <Col sm="4">
                                        <Button variant="info" ref="chgTesterBtn" disabled={!(
                                            (this.props.developer.uid === this.props.myuid) && 
                                            (this.props.deployStatus === TaskStatus.WAIT_FOR_TEST || this.props.deployStatus === TaskStatus.TESTING || this.props.deployStatus === TaskStatus.TEST_FAILED)
                                        )} onClick={this.handleChgTester.bind(this)}>修改</Button>
                                    </Col>
                                </Form.Group>
                            </Form>
                            <Form>
                                <Form.Group as={Row}>
                                    <Form.Label column sm="3">
                                        上线人员
                                    </Form.Label>
                                    <Col sm="5">
                                        <Form.Control ref="admin" as="select" disabled={this.props.developer.uid !== this.props.myuid}/>
                                    </Col>
                                    <Col sm="4">
                                        <Button variant="info" ref="chgAdminBtn" disabled={!(
                                            (this.props.developer.uid === this.props.myuid) && 
                                            (this.props.deployStatus === TaskStatus.WAIT_FOR_TEST || this.props.deployStatus === TaskStatus.TESTING || this.props.deployStatus === TaskStatus.TEST_FAILED || this.props.deployStatus === TaskStatus.WAIT_FOR_DEPLOY)
                                        )} onClick={this.handleChgReviewer.bind(this)}>修改</Button>
                                    </Col>
                                </Form.Group>
                            </Form>
                            <Form className="deployStatus">
                                <Form.Group as={Row}>
                                    <Form.Label column sm="3">
                                        当前状态
                                    </Form.Label>
                                    <Col sm="5">
                                    {this.props.deployStatus === TaskStatus.WAIT_FOR_TEST ? <div className={classNames("status", "text-success")}>等待测试</div> : null}
                                    {this.props.deployStatus === TaskStatus.TESTING ? <div className={classNames("status", "text-warning")}>测试中</div> : null}
                                    {this.props.deployStatus === TaskStatus.TEST_FAILED ? <div className={classNames("status", "text-danger")}>暂停测试</div> : null}
                                    {this.props.deployStatus === TaskStatus.WAIT_FOR_DEPLOY ? <div className={classNames("status", "text-dark")}>待上线</div> : null}
                                    {this.props.deployStatus === TaskStatus.PRE_TESTING ? <div className={classNames("status", "text-warning")}>预发布测试中</div> : null}
                                    {this.props.deployStatus === TaskStatus.PRE_TESTING_SUCCESS ? <div className={classNames("status", "text-success")}>预发布测试通过</div> : null}
                                    {this.props.deployStatus === TaskStatus.PRE_TESTING_FAIL ? <div className={classNames("status", "text-danger")}>预发布暂停测试</div> : null}
                                    {this.props.deployStatus === TaskStatus.DEPLOY_FAILED ? <div className={classNames("status", "text-danger")}>上线失败</div> : null}
                                    {this.props.deployStatus === TaskStatus.DEPLOYING ? <div className={classNames("status", "text-warning")}>上线中</div> : null}
                                    {this.props.deployStatus === TaskStatus.DEPLOY_SUCCESS ? <div className={classNames("status", "text-success")}>上线成功</div> : null}
                                    </Col>
                                    <Col sm="4">
                                        {this.props.deployStatus === TaskStatus.WAIT_FOR_TEST && (this.props.taskServs[0].servsObject.testHost == null || this.props.taskServs[0].servsObject.testHost.length === 0) ? 
                                            <Button onClick={this.handleTesting.bind(this, true)} variant="primary" disabled={!(this.props.tester.uid === this.props.myuid)}>开始测试</Button> 
                                        : null}
                                        {this.props.deployStatus === TaskStatus.TEST_FAILED && (this.props.taskServs[0].servsObject.testHost == null || this.props.taskServs[0].servsObject.testHost.length === 0) ? 
                                            <Button onClick={this.handleTesting.bind(this, true)} variant="primary" disabled={!(this.props.tester.uid === this.props.myuid)}>继续测试</Button> 
                                        : null}
                                        {this.props.deployStatus === TaskStatus.WAIT_FOR_DEPLOY || this.props.deployStatus === TaskStatus.PRE_TESTING_SUCCESS ? 
                                            <Button variant="success" size="sm" disabled={!(this.props.admin.uid === this.props.myuid)} onClick={this.handleDeploy.bind(this, false)}>上线</Button> 
                                        : null}
                                        {this.props.deployStatus === TaskStatus.DEPLOYING ? 
                                            <Button variant="danger" size="sm" disabled={!(
                                                this.props.canDeployConnect && (this.props.admin.uid === this.props.myuid)
                                                ) ? true : false
                                            } onClick={this.handleDeployFailured.bind(this)}>标注失败</Button> 
                                        : null}
                                        {this.props.deployStatus === TaskStatus.DEPLOY_FAILED ? 
                                            <Button  variant="warning" size="sm" disabled={!(
                                                this.props.canDeployConnect && (this.props.admin.uid === this.props.myuid)
                                                ) ? true : false
                                            } onClick={this.handleDeploy.bind(this, false)}>重新上线</Button> 
                                        : null}
                                    </Col>
                                </Form.Group>
                            </Form>
                            {(this.props.deployStatus === TaskStatus.WAIT_FOR_TEST || this.props.deployStatus === TaskStatus.TESTING || this.props.deployStatus === TaskStatus.TEST_FAILED) && this.props.taskServs[0].servsObject.testHost != null && this.props.taskServs[0].servsObject.testHost.length > 0 ? 
                                <Form className="deployStatus">
                                    <Form.Group as={Row}>
                                        <Form.Label column sm="3">
                                            测试环境
                                        </Form.Label>
                                        <Col sm="5">
                                            <Form.Control ref="testHost" as="select">
                                            {this.props.taskServs[0].servsObject.testHost.map(item => <option key={item} value={item}>{item}</option>)}     
                                            </Form.Control>
                                        </Col>
                                        <Col sm="4">
                                            {this.props.deployStatus === TaskStatus.WAIT_FOR_TEST ? <Button onClick={this.handleTesting.bind(this, true)} variant="primary" disabled={!(this.props.tester.uid === this.props.myuid)}>部署测试</Button> : null}
                                            {this.props.deployStatus === TaskStatus.TEST_FAILED ? <Button onClick={this.handleTesting.bind(this, true)} variant="primary" disabled={!(this.props.tester.uid === this.props.myuid)}>重新部署</Button> : null}
                                        </Col>
                                    </Form.Group>
                                    {this.props.deployStatus === TaskStatus.TESTING ? 
                                        <Fragment>
                                            <Form.Group as={Row} className="testDeployStatus">
                                                <Form.Label column sm="3">
                                                    操作
                                                </Form.Label>
                                                <Col sm="7">
                                                    <Button onClick={this.handleTesting.bind(this, false)} variant="primary" disabled={!(this.props.tester.uid === this.props.myuid || this.props.developer.uid === this.props.myuid)}>迭代部署</Button>
                                                    <Button onClick={this.handleTesting.bind(this, true)} variant="secondary" disabled={!(this.props.tester.uid === this.props.myuid || this.props.developer.uid === this.props.myuid)}>重新部署</Button>
                                                </Col>
                                            </Form.Group>
                                            <Form.Group as={Row} className="testDeployStatus">
                                                <Form.Label column sm="3">
                                                    测试结果
                                                </Form.Label>
                                                <Col sm="7">
                                                    <Button variant="success" onClick={this.handleTestSuccess.bind(this)} disabled={!(this.props.tester.uid === this.props.myuid)}>测试通过</Button>
                                                    <Button variant="danger" onClick={this.abortTest.bind(this)} disabled={!(this.props.tester.uid === this.props.myuid)}>暂停测试</Button>
                                                </Col>
                                            </Form.Group>
                                        </Fragment>
                                    : null}
                                </Form>         
                            : null}
                            {(this.props.deployStatus === TaskStatus.WAIT_FOR_DEPLOY || this.props.deployStatus === TaskStatus.PRE_TESTING || this.props.deployStatus === TaskStatus.PRE_TESTING_FAIL) && this.props.taskServs[0].servsObject.prevHost != null && this.props.taskServs[0].servsObject.prevHost.length > 0 ? 
                                <Form className="deployStatus">
                                    <Form.Group as={Row}>
                                        <Form.Label column sm="3">
                                            预发布
                                        </Form.Label>
                                        <Col sm="5">
                                            <Form.Control ref="prevHost" as="select">
                                            {this.props.taskServs[0].servsObject.prevHost.map(item => <option key={item} value={item}>{item}</option>)}     
                                            </Form.Control>
                                        </Col>
                                        <Col sm="4">
                                            {this.props.deployStatus === TaskStatus.WAIT_FOR_DEPLOY ? <Button onClick={this.handlePreTesting.bind(this, true)} variant="primary" disabled={!(this.props.admin.uid === this.props.myuid)}>测试</Button> : null}
                                            {this.props.deployStatus === TaskStatus.PRE_TESTING_FAIL ? <Button onClick={this.handlePreTesting.bind(this, true)} variant="primary" disabled={!(this.props.admin.uid === this.props.myuid)}>继续测试</Button> : null}
                                        </Col>
                                    </Form.Group>
                                    {this.props.deployStatus === TaskStatus.PRE_TESTING ? 
                                        <Fragment>
                                            <Form.Group as={Row} className="testDeployStatus">
                                                <Form.Label column sm="3">
                                                    操作
                                                </Form.Label>
                                                <Col sm="7">
                                                    <Button onClick={this.handlePreTesting.bind(this, false)} variant="primary" disabled={!(this.props.tester.uid === this.props.myuid || this.props.admin.uid === this.props.myuid || this.props.developer.uid === this.props.myuid)}>迭代部署</Button>
                                                    <Button onClick={this.handlePreTesting.bind(this, true)} variant="secondary" disabled={!(this.props.tester.uid === this.props.myuid || this.props.admin.uid === this.props.myuid || this.props.developer.uid === this.props.myuid)}>重新部署</Button>
                                                </Col>
                                            </Form.Group>
                                            <Form.Group as={Row} className="testDeployStatus">
                                                <Form.Label column sm="3">
                                                    测试结果
                                                </Form.Label>
                                                <Col sm="7">
                                                    <Button variant="success" onClick={this.handlePreTestSuccess.bind(this)} disabled={!(this.props.tester.uid === this.props.myuid)}>测试通过</Button>
                                                    <Button variant="danger" onClick={this.abortPreTest.bind(this)} disabled={!(this.props.tester.uid === this.props.myuid)}>暂停测试</Button>
                                                </Col>
                                            </Form.Group>
                                        </Fragment>
                                    : null}
                                </Form>         
                            : null}
                        </Col>
                    </Row>
                </div>
                {this.props.canDeployConnect && (
                    (this.props.deployStatus === TaskStatus.TESTING && this.state.testHost !== null) ||
                    (this.props.deployStatus === TaskStatus.PRE_TESTING && this.state.prevHost !== null) ||
                    this.props.deployStatus === TaskStatus.DEPLOYING ||
                    this.props.deployStatus === TaskStatus.DEPLOY_FAILED ||
                    this.props.deployStatus === TaskStatus.DEPLOY_SUCCESS
                ) ? <DeployContainer 
                    onRef={this.onDeployContainerRef} 
                    pid={this.state.pid} tid={this.state.tid} 
                    onFinish={this.getTask.bind(this)}
                    /> : null}
            </Container>
        )
    }
}

function mapStateToProps (state) {
    return {
        deployUrl: state.deploy.deployUrl,
        taskName: state.tasks.taskName,
        markContent: state.tasks.markContent,
        deployStatus: state.tasks.deployStatus,
        taskServs: state.tasks.serversList,
        admin: state.tasks.admin,
        tester: state.tasks.tester,
        developer: state.tasks.developer,
        myuid: state.account.uid,
        projectList: state.project,
        canDeployConnect: state.deploy.canDeployConnect,
    }
  }
  
  export default connect(mapStateToProps)(App);